package com.grm.sys.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.grm.common.Result;
import com.grm.sys.entity.SysRole;
import com.grm.sys.entity.SysRoleMenu;
import com.grm.sys.entity.SysUserRole;
import com.grm.sys.service.SysMenuService;
import com.grm.sys.service.SysRoleMenuService;
import com.grm.sys.service.SysRoleService;
import com.grm.sys.service.SysUserRoleService;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 系统角色控制器
 *
 * @author gaorimao
 * @date 2022/02/14
 */
@RestController
@RequestMapping("/sys/role")
public class SysRoleController {
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 插入系统角色
     *
     * @param sysRole 系统角色
     * @return {@link Result}
     */
    @PreAuthorize("hasAuthority('sys:role:add')")
    @PostMapping("/insert")
    public Result insert(@RequestBody SysRole sysRole) {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", sysRole.getCode());
        SysRole dbSysRole = sysRoleService.getOne(queryWrapper);
        if (dbSysRole != null) {
            return Result.failed(500,"角色已存在，不能重复添加！");
        }
        sysRole.setCreated(new Date());
        sysRoleService.save(sysRole);
        return Result.success("添加系统角色成功！");
    }

    /**
     * 修改系统角色
     *
     * @param sysRole 系统角色
     * @return {@link Result}
     */
    @PreAuthorize("hasAuthority('sys:role:update')")
    @PutMapping("/update")
    public Result update(@RequestBody SysRole sysRole) {
        // 修改时间
        sysRole.setUpdated(new Date());
        QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
        wrapper.eq("id", sysRole.getId());
        sysRoleService.update(sysRole, wrapper);
        return Result.success("修改系统角色成功！");
    }

    /**
     * 给系统角色分配权限
     *
     * @param sysRoleId 系统角色id
     * @return {@link Result}
     */
    @PreAuthorize("hasAuthority('sys:role:givePerms')")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/givePerms/{sysRoleId}")
    public Result givePerms(@PathVariable Long sysRoleId, @RequestBody List<Long> sysMenuIds) {
        // 删除角色权限关联关系
        QueryWrapper<SysRoleMenu> sysRoleMenuQueryWrapper = new QueryWrapper<>();
        sysRoleMenuQueryWrapper.eq("role_id", sysRoleId);
        sysRoleMenuService.remove(sysRoleMenuQueryWrapper);
        // 重新赋予角色和权限关联关系
        List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
        Optional.ofNullable(sysMenuIds).orElse(new ArrayList<>()).stream().forEach(menuId -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(sysRoleId);
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenus.add(sysRoleMenu);
        });

        sysRoleMenuService.saveBatch(sysRoleMenus);
        return Result.success("给系统角色分配权限成功！");
    }

    /**
     * 查询用户所拥有的系统角色
     *
     * @param userId 用户id
     * @return {@link Result}
     */
    @PreAuthorize("hasAuthority('sys:user:getRoles')")
    @GetMapping("/query/{userId}")
    public Result querySysRolesByUserId(@PathVariable Long userId) {
        List<SysRole> sysRoles = sysRoleService.querySysRolesByUserId(userId);
        return Result.success("查询用户下的角色信息成功！", sysRoles);
    }

    /**
     * 查询系统所有角色
     *
     * @return {@link Result}
     */
    @PreAuthorize("hasAuthority('sys:role:getAll')")
    @GetMapping("/query/all")
    public Result querySysRolesAll() {
        List<SysRole> sysRoles = sysRoleService.list();
        return Result.success("查询全部的角色信息成功！", sysRoles);
    }

    /**
     * 条件查询，带分页
     *
     * @param pageNum  页码
     * @param pageSize 页大小
     * @param sysRole  系统角色
     * @return {@link Result}
     */
    @PreAuthorize("hasAuthority('sys:role:list')")
    @PostMapping("/query/selective")
    public Result querySelective(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestBody SysRole sysRole) {
        //使用分页插件
        PageHelper.startPage(pageNum, pageSize);
        // 查询条件
        QueryWrapper<SysRole> wrapper = getQueryWrapper(sysRole);
        List<SysRole> sysRoleList = sysRoleService.list(wrapper);
        //获取总数
        PageInfo<SysRole> pageInfo = new PageInfo<>(sysRoleList);
        Long total = pageInfo.getTotal();
        return Result.success("查询系统角色列表成功！", sysRoleList, total);
    }

    /**
     * 删除系统角色
     *
     * @param id 系统角色id
     * @return {@link Result}
     */
    @Transactional(rollbackFor = Exception.class)
    @PreAuthorize("hasAuthority('sys:role:delete')")
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Long id) {
        // 删除角色
        sysRoleService.removeById(id);
        // 删除用户角色关联
        QueryWrapper<SysUserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.eq("role_id",id);
        sysUserRoleService.remove(userRoleQueryWrapper);
        // 删除角色菜单关联
        QueryWrapper<SysRoleMenu> roleMenuQueryWrapper = new QueryWrapper<>();
        roleMenuQueryWrapper.eq("role_id",id);
        sysRoleMenuService.remove(roleMenuQueryWrapper);
        return Result.success("删除系统角色成功！");
    }

    /**
     * 批量删除系统角色
     *
     * @param sysRoles 系统角色s
     * @return {@link Result}
     */
    @Transactional(rollbackFor = Exception.class)
    @PreAuthorize("hasAuthority('sys:role:batch:delete')")
    @PostMapping("/batch/delete")
    public Result batchDelete(@RequestBody List<SysRole> sysRoles) {
        List<Long> roleIds = sysRoles.stream().map(SysRole::getId).collect(Collectors.toList());
        // 删除角色
        sysRoleService.removeBatchByIds(roleIds);
        // 删除用户角色关联
        QueryWrapper<SysUserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.in("role_id",roleIds);
        sysUserRoleService.remove(userRoleQueryWrapper);
        // 删除角色菜单关联
        QueryWrapper<SysRoleMenu> roleMenuQueryWrapper = new QueryWrapper<>();
        roleMenuQueryWrapper.in("role_id",roleIds);
        sysRoleMenuService.remove(roleMenuQueryWrapper);
        return Result.success("批量删除系统角色成功！");
    }

    /**
     * 封装查询条件的方法
     *
     * @param sysRole 系统角色
     * @return {@link QueryWrapper}<{@link SysRole}>
     */
    private QueryWrapper<SysRole> getQueryWrapper(SysRole sysRole) {
        QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(sysRole.getName())) {
            wrapper.like("name", sysRole.getName());
        }
        if (ObjectUtils.isNotEmpty(sysRole.getCode())) {
            wrapper.like("code", sysRole.getCode());
        }
        wrapper.orderByDesc("created");
        return wrapper;
    }
}
